import {
    AbstractBookCrawler,
    BasicBook,
    BasicChapter,
    Book,
    request,
    SearchBookResult,
    BookCrawlerTest,
    BookSource
} from '../../common/common_node.js'


class BookCrawler extends AbstractBookCrawler {

    async searchBook(keyword, pageNum) {
        function getBookList($) {
            const bookArr = [];
            const aListBoxArr = $("#hotcontent #alistbox");
            aListBoxArr.each(function (index, elem) {
                const info = $(this).find(".info .title a");
                bookArr.push(new BasicBook({
                    name: info.text(),
                    author: $(this).find(".info .title span").text().replace('作者：', ''),
                    path: info.attr("href"),
                }));
            });
            return bookArr;
        }

        async function fetchMulti(pageUrl) {
            return request(pageUrl)
                .then((response) => response.doc())
                .then((doc) => {
                    return getBookList(doc);
                });
        }

        let url = this.source.searchBaseUrl + '/search.html?searchkey=' + encodeURIComponent(keyword);
        const $ = await (await request(url)).doc();
        //获取当页目录
        const bookArr = getBookList($);
        const pageLinkArr = $("#pagelink a");
        let pageArr = [];
        if (pageLinkArr.length > 1) {
            //如果有多页
            pageLinkArr.each(function (index, elem) {
                if (index !== 0) {
                    const pageUrl = this.source.searchBaseUrl + $(this).attr("href");
                    pageArr.push(pageUrl)
                }
            })
            const promises = pageArr.map((pageUrl) => fetchMulti(pageUrl));
            let pages = await Promise.all(promises)
            for (const iterator of pages) {
                bookArr.push(...iterator);
            }
        }

        return new SearchBookResult({
            pageNum: 1,
            pages: 1,
            keyword: keyword,
            bookList: bookArr
        });
    }

    async bookDetails(path) {
        const $ = await (await request(this.source.bookBaseUrl + path)).doc();
        const name = $("meta[property='og:novel:book_name']").attr("content");
        return new Book({
            name: name,
            author: $("meta[property='og:novel:author']").attr("content"),
            path: path,
            intro: $("meta[property='og:description']").attr("content").replace('关于' + name + '：', ''),
            coverUrl: $("meta[property='og:image']").attr("content"),
            type: $("meta[property='og:novel:category']").attr("content")
        });
    }

    async bookCatalog(path) {
        const $ = await (await request(this.source.bookBaseUrl + path)).doc();
        const chapters = $('#list dt:eq(1)').nextAll('dd').find('a');
        let index = 0;
        let catalog = [];
        chapters.each(function (i, elem) {
            const item = $(this);
            catalog.push(new BasicChapter({
                index: index++,
                title: item.text(),
                path: item.attr("href")
            }));
        });
        return catalog;
    }

    async chapterContent(path) {
        const $ = await (await request(this.source.bookBaseUrl + path)).doc();
        $("#content .bottem").remove();
        $("#content p:last-child").remove();
        let content = '';
        const pTags = $("#content p");
        pTags.each(function (index) {
            content += $(this).text();
            // 如果不是最后一个p标签，则添加换行符
            if (index !== pTags.length - 1) {
                content += '\n';
            }
        });
        let next = $(".bottem1 a:eq(3)");
        if (next.text().includes("下一页")) {
            content += "\n" + await this.chapterContent(next.attr("href"));
        }
        return content;
    }
}

const source = {
    "id": "free-book-js/1",
    "name": "33言情",
    "active": true,
    "portalUrl": "https://www.x33yq.org",
    "searchBaseUrl": "https://www.x33yq.org",
    "bookBaseUrl": "https://www.x33yq.org"
};

await new BookCrawlerTest(new BookCrawler(BookSource.createTestBookSource(source)), {
    enableSearch: false,
    bookPath: "/read/115107/"
}).run();

